//////////////////////////////////////////////////////////////////////////////////////////////////////
// 项目名   : ActorAndCSPDesignPatterns
// 文件名   : Actor.h
// 作者     : Aiye
// 日期     : 2025/10/1 14:22
// 邮箱     : 2878548868@qq.com
// 摘要     : 
//////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef ACTORANDCSPDESIGNPATTERNS_ACTOR_H
#define ACTORANDCSPDESIGNPATTERNS_ACTOR_H
#include <condition_variable>
#include <functional>
#include <future>
#include <mutex>
#include <queue>

class Actor
{
public:
    Actor()
    {
        _worker = std::thread{[this]()
        {
            while (_bRunning)
            {
                std::function<void()> task{};
                {
                    std::unique_lock lock{_mtx};
                    _cv.wait(lock, [&]()
                    {
                        return !_mailbox.empty() || !_bRunning;
                    }); // 等待

                    if (_bRunning && _mailbox.empty())
                    {
                        break;
                    }

                    task = std::move(_mailbox.front()); // 取出第一个任务
                    _mailbox.pop();
                }
                task(); // 执行任务
            }
        }}; // 创建一个线程，该线程负责处理消息队列中的任务
    }

    ~Actor()
    {
        {
            std::lock_guard lock{_mtx};
            _bRunning = false;
        }
        _cv.notify_all();
        _worker.join();
    }

    void send(std::function<void()> msg)
    {
        {
            std::lock_guard lock{_mtx};
            _mailbox.push(std::move(msg));
        }
        _cv.notify_one();
    }

private:
    std::queue<std::function<void()>> _mailbox{};   // 消息队列，用于储存从其他Actor中收到的消息
    std::mutex _mtx{};                              // 互斥锁，保护对消息队列的访问
    std::condition_variable _cv{};                  // 条件变量，用于再消息队列为空时阻塞处理线程，并在新消息时唤醒它
    bool _bRunning{true};                           // 标志位，表示Actor是否正在运行
    std::thread _worker{};                          // 处理线程，负责从消息队列中取出消息并执行
};

class Calculator : public Actor
{
public:
    template<typename Func , typename... Params>
    auto calculator(Func func , Params... params) -> std::future<decltype(func(params...))>
    {
        auto promise = std::make_shared<std::promise<decltype(func(params...))>>();
        auto fut = promise->get_future();
        send([=]()
        {
           promise->set_value(func(params...));
        });
        return fut;
    }
};

#endif //ACTORANDCSPDESIGNPATTERNS_ACTOR_H